﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using System.Collections;

namespace SPUtility
{
   public class WorkflowHelper
    {
       string taskApprovalRepository = "TaskApprovalRepository";
       Dictionary<string, string> Dict = new Dictionary<string, string>();
       public bool RjectWFProcess(string siteUrl, string listName, string fieldName, string itemID, string workflowAssociationName, string currentApprovalLevel)
       {
           bool status = false;
           using (SPSite site = new SPSite(siteUrl))
           {
               using (SPWeb objWeb = site.OpenWeb())
               {
                   SPList list = objWeb.Lists[listName];
                   SPListItem item = null;// list.Items.GetItemById(itemID);
                   foreach (SPListItem item1 in list.Items)
                   {
                       if (item1[fieldName] != null && item1[fieldName].ToString() == itemID)
                       {
                           item = item1;
                           break;
                       }
                   }
                   if (item == null)
                   {
                       return false;
                   }
                   //SPWorkflowTemplate template =          objWeb.WorkflowTemplates.GetTemplateByName("Approval", objWeb.Locale);
                   Console.WriteLine(item.Title);
                   var tskC = (from SPWorkflow spwfa in item.Workflows
                               where spwfa.AssociationId ==
                               (
                                   (
                                    from SPWorkflowAssociation associ in list.WorkflowAssociations
                                    where associ.Name.Equals(workflowAssociationName, StringComparison.CurrentCultureIgnoreCase)
                                    select associ.Id
                                    )
                                 .
                                 FirstOrDefault()
                                 )
                               select spwfa.Tasks
                              ).FirstOrDefault();

                   foreach (SPWorkflowTask tsk in tskC)// item.Tasks)
                   {

                       Console.WriteLine(list.WorkflowAssociations[0].Id);
                       Console.WriteLine(tsk.Name);
                       Console.WriteLine(tsk.ID);
                       Console.WriteLine(tsk.Title);
                       // alter the task
                       Hashtable ht = new Hashtable();
                       ht[SPBuiltInFieldId.Completed] = "TRUE";
                       ht[SPBuiltInFieldId.PercentComplete] = 1;
                       ht[SPBuiltInFieldId.TaskStatus] = "Completed";//SPResource.GetString(new CultureInfo((int)objWeb.Language, false), "WorkflowTaskStatusComplete", new object[0]);
                       ht["ApprovalStatus"] = "Reject";

                       Dict.Add("Title", tsk.Title);
                       Dict.Add("TaskOutCome", "Reject");
                       Dict.Add("ShortDescription", tsk.Title + "___>" + itemID);
                       Dict.Add("WFTaskInstanceConfigID", item.ID.ToString() );
                       Dict.Add("ApprovalLevel", currentApprovalLevel);
                       // Mark the entry as approved
                       status = SPWorkflowTask.AlterTask((tsk as SPListItem), ht, true);
                       AddToLog(siteUrl, taskApprovalRepository);
                       break;
                   }

                   //objWeb.Update();
               }
           }

         
           return status;
       }

       private void AddToLog(string siteUrl, string listName)
       {
           //ListActivity lstActivity = new ListActivity();
         //  lstActivity.AddItem(siteUrl, listName, Dict);
       }


       public bool ApproveWFProcess(string siteUrl, string listName, string fieldName, string itemID, string workflowAssociationName, string currentApprovalLevel, Guid taskUniqueGuid)
       {
           bool status = false;
           using (SPSite site = new SPSite(siteUrl))
           {
               using (SPWeb objWeb = site.OpenWeb())
               {
                   SPList list = objWeb.Lists[listName];
                   SPListItem item = null;// list.Items.GetItemById(itemID);
                   foreach (SPListItem item1 in list.Items)
                   {
                       if ( item1[fieldName] !=null && item1[fieldName].ToString() == itemID)
                       {
                           item = item1;
                           break;
                       }
                   }
                   if (item == null)
                   {
                       return false;
                   }
                   //SPWorkflowTemplate template =          objWeb.WorkflowTemplates.GetTemplateByName("Approval", objWeb.Locale);
                   Console.WriteLine(item.Title);
                   var tskC = (from SPWorkflow spwfa in item.Workflows
                               where spwfa.AssociationId ==
                               (
                                   (
                                    from SPWorkflowAssociation associ in list.WorkflowAssociations
                                    where associ.Name.Equals(workflowAssociationName, StringComparison.CurrentCultureIgnoreCase)
                                    select associ.Id
                                    )
                                 .
                                 FirstOrDefault()
                                 )
                               select spwfa.Tasks
                              ).FirstOrDefault();

                   foreach (SPWorkflowTask tsk in tskC)// item.Tasks)
                   {

                       Console.WriteLine(list.WorkflowAssociations[0].Id);
                       Console.WriteLine(tsk.Name);
                       Console.WriteLine(tsk.ID);
                       Console.WriteLine(tsk.Title);
                       // alter the task
                       Hashtable ht = new Hashtable();
                       ht[SPBuiltInFieldId.Completed] = "TRUE";
                       ht[SPBuiltInFieldId.PercentComplete] = 1;
                       ht[SPBuiltInFieldId.TaskStatus] = "Completed";//SPResource.GetString(new CultureInfo((int)objWeb.Language, false), "WorkflowTaskStatusComplete", new object[0]);
                       ht["ApprovalStatus"] = "Accept";
                       ht["TaskUniqueID"] = taskUniqueGuid;


                       Dict.Add("Title", tsk.Title);
                       Dict.Add("TaskOutCome", "Accept");
                       Dict.Add("ShortDescription", tsk.Title + "  {" + itemID + "}");
                       Dict.Add("WFTaskInstanceConfigID", item.ID.ToString());
                       Dict.Add("ApprovalLevel", currentApprovalLevel);

                       // Mark the entry as approved
                       status = SPWorkflowTask.AlterTask((tsk as SPListItem), ht, true);
                       AddToLog(siteUrl, taskApprovalRepository);
                       break;
                   }

                   //objWeb.Update();
               }
           }
           return status;
       }


       public bool ApproveWFProcess(string siteUrl , string listName, int itemID, string workflowAssociationName, string currentApprovalLevel )
       {
           bool status = false;
           using (SPSite site = new SPSite(siteUrl))
           {
               using (SPWeb objWeb = site.OpenWeb())
               {
                   SPList list = objWeb.Lists[listName];
                   SPListItem item = list.Items.GetItemById(itemID);
                   //SPWorkflowTemplate template =          objWeb.WorkflowTemplates.GetTemplateByName("Approval", objWeb.Locale);
                   Console.WriteLine(item.Title);
                   var tskC = (from SPWorkflow spwfa in item.Workflows
                               where spwfa.AssociationId ==
                               (
                                   (
                                    from SPWorkflowAssociation associ in list.WorkflowAssociations
                                    where associ.Name.Equals(workflowAssociationName, StringComparison.CurrentCultureIgnoreCase)
                                    select associ.Id
                                    )
                                 .
                                 FirstOrDefault()
                                 )
                               select spwfa.Tasks
                              ).FirstOrDefault();
                  
                   foreach (SPWorkflowTask tsk in tskC)// item.Tasks)
                   {

                       Console.WriteLine(list.WorkflowAssociations[0].Id);
                       Console.WriteLine(tsk.Name);
                       Console.WriteLine(tsk.ID);
                       Console.WriteLine(tsk.Title);
                       // alter the task
                       Hashtable ht = new Hashtable();
                       ht[SPBuiltInFieldId.Completed] = "TRUE";
                       ht[SPBuiltInFieldId.PercentComplete] = 1;
                       ht[SPBuiltInFieldId.TaskStatus] = "Completed";//SPResource.GetString(new CultureInfo((int)objWeb.Language, false), "WorkflowTaskStatusComplete", new object[0]);
                       ht["ApprovalStatus"] = "Accept";


                       Dict.Add("Title", tsk.Title);
                       Dict.Add("TaskOutCome", "Accept");
                       Dict.Add("ShortDescription", tsk.Title + "___>" + itemID);
                       Dict.Add("WFTaskInstanceConfigID", item.ID.ToString() );
                       Dict.Add("ApprovalLevel", currentApprovalLevel);
                       // Mark the entry as approved
                       status = SPWorkflowTask.AlterTask((tsk as SPListItem), ht, true);
                       AddToLog(siteUrl, taskApprovalRepository);
                       break;
                   }

                   //objWeb.Update();
               }
           }
           return status;
       }

       public bool CancelWFProcess(string siteUrl, string listName, int itemID, string workflowAssociationName, string currentApprovalLevel)
       {
           using (SPSite site = new SPSite(siteUrl))
           {
               using (SPWeb objWeb = site.OpenWeb())
               {
                   SPList list = objWeb.Lists[listName];
                   SPListItem item = list.Items.GetItemById(itemID);
                   //SPWorkflowTemplate template =          objWeb.WorkflowTemplates.GetTemplateByName("Approval", objWeb.Locale);
                   Console.WriteLine(item.Title);
                   var tskC = (from SPWorkflow spwfa in item.Workflows
                               where spwfa.AssociationId ==
                               (
                                   (
                                    from SPWorkflowAssociation associ in list.WorkflowAssociations
                                    where associ.Name.Equals(workflowAssociationName, StringComparison.CurrentCultureIgnoreCase)
                                    select associ.Id
                                    )
                                 .
                                 FirstOrDefault()
                                 )
                               select spwfa
                              ).FirstOrDefault();


                   if (tskC != null)
                   {

                       Dict.Add("Title", item.Title);
                       Dict.Add("TaskOutCome", "Cancelled");
                       Dict.Add("ShortDescription", item.Title + "___>" + itemID);
                       Dict.Add("WFTaskInstanceConfigID", item.ID.ToString());
                       Dict.Add("ApprovalLevel", currentApprovalLevel);

                       SPWorkflowManager.CancelWorkflow(tskC);
                       AddToLog(siteUrl, taskApprovalRepository);
                       return true;
                   }
               }
           }
           return false;
       }


       private DateTime ActualDate(DateTime curDate, int Days, SPList holidayList)
       {
           int k = 1;
           double actualDays = 1;
           string weekend1 = "sunday";
           string weekend2 = "saturday";
           while (k <= Days)
           {
               if (
                   !curDate.AddDays(actualDays).DayOfWeek.ToString().Equals(weekend1, StringComparison.CurrentCultureIgnoreCase)
                   &&
                   !curDate.AddDays(actualDays).DayOfWeek.ToString().Equals(weekend2, StringComparison.CurrentCultureIgnoreCase)
                   )
               {
                   var dat = (from SPListItem itm in holidayList.Items
                              where itm["HolidayDate"] != null &&
                             String.Format("{0:d}", (DateTime)itm["HolidayDate"]) == String.Format("{0:d}", curDate.AddDays(actualDays))
                              select itm).FirstOrDefault();
                   if (dat == null)
                   {

                       k++;
                   }
               }

               actualDays++;
               // k++;

           }
           if (Days == 0)
           {


               var dat1 = (from SPListItem itm in holidayList.Items
                           where itm["HolidayDate"] != null &&
                          String.Format("{0:d}", (DateTime)itm["HolidayDate"]) == String.Format("{0:d}", curDate)
                           select itm).FirstOrDefault();
               if (dat1 != null)
               {
                   // curDate = curDate.AddDays(1);
                   return ActualDate(curDate.AddDays(1), 1, holidayList);
               }
           }
           else
           {
               actualDays = (k > 0 ? actualDays - 1 : actualDays);
           }
           if (
                   curDate.AddDays(actualDays).DayOfWeek.ToString().Equals(weekend1, StringComparison.CurrentCultureIgnoreCase)
                   ||
                   curDate.AddDays(actualDays).DayOfWeek.ToString().Equals(weekend2, StringComparison.CurrentCultureIgnoreCase)
                   )
           {


               return ActualDate(curDate.AddDays(actualDays + 1), 0, holidayList);
               //actualDays++;
           }


           return curDate.AddDays(actualDays);
       }
       public void ProcessBatchInsert(string siteUrl, string targetListGuid, string workflowName, string taskFields, int WFItemID, string SourceListTitle, string ListUrl)
       {
           //double aa = ActualDays(5);

           double hourDiff = (24 - (System.DateTime.Now.Minute + 1) / 60D);
           hourDiff = Math.Round(hourDiff, 2) - System.DateTime.Now.Hour;
           // return;
           // string listGuid = "C7F6A36F-BD2E-484A-A18C-05D9F69AC554";
           StringBuilder query = new StringBuilder();

           using (SPSite site = new SPSite(siteUrl))
           {

               using (SPWeb objWeb = site.OpenWeb())
               {
                   SPList configList = objWeb.Lists["ApprovalLevel"];
                   SPList holidayList = objWeb.Lists["Holiday"];
                   StringBuilder sbHoliday = new StringBuilder();

                   var listItem = (from SPListItem itm in configList.Items
                                   where
                                   itm["Project"] != null
                                   &&
                                   itm["Project"].ToString().Contains(";#" + workflowName)
                                   select itm);

                   StringBuilder query1 = new StringBuilder();
                   DateTime curDate = System.DateTime.Now;
                   foreach (var item in listItem)
                   {
                       query.AppendFormat(
                      "<Method ID=\"{0}\">" +
                      "<SetList>{1}</SetList>" +
                      "<SetVar Name=\"ID\">New</SetVar>" +
                      "<SetVar Name=\"Cmd\">Save</SetVar>", item.ID, targetListGuid);
                       foreach (string fld in taskFields.Replace("\r", "").Replace("\n", "").Replace(" ", "").Split(','))
                       {
                           query.AppendFormat("<SetVar Name=\"{1}\">{0}</SetVar>", WFItemID, "urn:schemas-microsoft-com:office:office#WFItemID");
                           query.AppendFormat("<SetVar Name=\"{1}\">{0}</SetVar>", SourceListTitle, "urn:schemas-microsoft-com:office:office#SourceListTitle");
                           query.AppendFormat("<SetVar Name=\"{1}\">{0}</SetVar>", ListUrl, "urn:schemas-microsoft-com:office:office#ListUrl");

                           if (fld.Contains("DueDate"))
                           {
                               curDate = ActualDate(curDate, int.Parse(item["TaskDueDays"].ToString()), holidayList);
                               query.AppendFormat("<SetVar Name=\"{1}\">{0}</SetVar>",
                                    Microsoft.SharePoint.Utilities.SPUtility.CreateISO8601DateTimeFromSystemDateTime(
                                   curDate.AddHours(
                                    hourDiff)),
                                    "urn:schemas-microsoft-com:office:office#" + fld);
                           }
                           else
                               query.AppendFormat("<SetVar Name=\"{1}\">{0}</SetVar>", item[fld], "urn:schemas-microsoft-com:office:office#" + fld);
                       }
                       query.AppendFormat("</Method>");
                   }

                   string output = objWeb.ProcessBatchData(string.Format("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                          "<ows:Batch OnError=\"Return\">{0}</ows:Batch>", query.ToString()));
                   Console.WriteLine(output);
               }
           }
       }
   

   
   }
}
